package com.yzcrm.erp.finance.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.paragetter.Para;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import com.yzcrm.common.annotation.NotNullValidate;
import com.yzcrm.common.annotation.Permissions;
import com.yzcrm.common.config.paragetter.BasePageRequest;
import com.yzcrm.erp.admin.entity.AdminFieldSort;
import com.yzcrm.erp.admin.service.AdminFieldService;
import com.yzcrm.erp.admin.service.AdminSceneService;
import com.yzcrm.erp.crm.common.CrmEnum;
import com.yzcrm.erp.crm.common.CrmExcelUtil;
import com.yzcrm.erp.finance.service.FinanceSupplierService;
import com.yzcrm.swagger.annotation.ActionApi;
import com.yzcrm.swagger.annotation.Api;
import com.yzcrm.swagger.annotation.Param;
import com.yzcrm.swagger.annotation.Params;
import com.yzcrm.utils.BaseUtil;
import com.yzcrm.utils.R;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author jiang.xue
 * 供应商管理
 */
@Api(remark = "财务：供应商管理")
public class FinanceSupplierController extends Controller{

    @Inject
    private FinanceSupplierService supplierService;

    @Inject
    private AdminFieldService adminFieldService;

//    @Inject
//    private AdminSceneService adminSceneService;

    /**
     * @author wyq
     * 查看列表页
     */
    @Permissions({"finance:supplier:index"})
    @ActionApi(summary = "检索供应商列表数据", remark="检索供应商列表数据")
    @Params({
            @Param(name="sceneId", remark="场景Id", dataType="int", defaultValue="", required=false),
            @Param(name="type", remark="权限标识 60：供应商（supplier）", dataType="int", defaultValue="", required=true)
    })
    public void queryPageList(BasePageRequest basePageRequest) {

        JSONObject jsonObject = basePageRequest.getJsonObject().fluentPut("type", CrmEnum.FINANCE_SUPPLIER.getType());
        basePageRequest.setJsonObject(jsonObject);
        renderJson(supplierService.filterConditionAndGetPageList(basePageRequest));
    }

    /**
     * 添加或者修改供应商
     */
    @ActionApi(summary = "添加或者修改供应商", remark="添加或者修改供应商")
    @Params({
            @Param(name="address", remark="地址，（辽宁省,大连市,高新园区）", dataType="String", defaultValue="", required=false),
            @Param(name="address_detail", remark="地址详细", dataType="String", defaultValue="", required=false),
            @Param(name="location", remark="定位", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"finance:supplier:save", "finance:supplier:update"})
    public void saveOrUpdate(){

        JSONObject jsonObject = JSON.parseObject(getRawData());
        renderJson(supplierService.addOrUpdate(jsonObject));
    }

    /**
     * @author wyq
     * 根据id删除供应商
     */
    @ActionApi(summary = "根据id删除供应商", remark="根据id删除供应商")
    @Params({
            @Param(name="supplierIds", remark="供应商ID 多个ID,逗号分割", dataType="String", defaultValue="", required=true)
    })
    @Permissions("finance:supplier:delete")
    @NotNullValidate(value = "supplierIds", message = "供应商id不能为空")
    public void deleteByIds(@Para("supplierIds") String supplierIds) {
        renderJson(supplierService.deleteByIds(supplierIds));
    }

    /**
     * @author wyq
     * 根据供应商id查询
     */
    @ActionApi(summary = "根据id查询供应商", remark="根据id查询供应商")
    @Params({
            @Param(name="supplierId", remark="供应商ID", dataType="String", defaultValue="", required=true)
    })
    @Permissions("finance:supplier:read")
    @NotNullValidate(value = "supplierId", message = "供应商id不能为空")
    public void queryById(@Para("supplierId") Integer supplierId) {
        renderJson(R.ok().put("data", supplierService.queryById(supplierId)));
    }


    /**
     * @author wyq
     * 获取导入模板
     */
    public void downloadExcel() {
        List<Record> recordList = adminFieldService.queryAddField(CrmEnum.FINANCE_SUPPLIER);
        recordList.removeIf(record -> "file".equals(record.getStr("formType")) || "checkbox".equals(record.getStr("formType")) || "user".equals(record.getStr("formType")) || "structure".equals(record.getStr("formType")));
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("供应商导入表");
        sheet.setDefaultRowHeight((short)400);
        CellStyle textStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        textStyle.setDataFormat(format.getFormat("@"));
        for (int i = 0; i < recordList.size() + 2; i++) {
            sheet.setDefaultColumnStyle(i,textStyle);
            sheet.setColumnWidth(i,20*256);
        }
        HSSFRow titleRow = sheet.createRow(0);
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = wb.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        cellStyle.setFont(font);
        titleRow.createCell(0).setCellValue("供应商导入模板(*)为必填项");
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleRow.getCell(0).setCellStyle(cellStyle);
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, recordList.size() + 1);
        sheet.addMergedRegion(region);
        try {
            HSSFRow row = sheet.createRow(1);
            for (int i = 0; i < recordList.size(); i++) {
                Record record = recordList.get(i);
                //省市区需特殊处理
                if ("map_address".equals(record.getStr("field_name"))) {
                    HSSFCell cell1 = row.createCell(i);
                    cell1.setCellValue("省");
                    HSSFCell cell2 = row.createCell(i + 1);
                    cell2.setCellValue("市");
                    HSSFCell cell3 = row.createCell(i + 2);
                    cell3.setCellValue("区");
                    HSSFSheet hideSheet = wb.createSheet("address");
                    wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
                    int rowId = 0;
                    // 设置第一行，存省的信息
                    Row provinceRow = hideSheet.createRow(rowId++);
                    provinceRow.createCell(0).setCellValue("省列表");
                    List<String> provinceList = Db.query("select city_name from yzcrm_crm_area where parent_id = ?", 0);

                    for (int x = 0; x < provinceList.size(); x++) {
                        Cell provinceCell = provinceRow.createCell(x + 1);
                        provinceCell.setCellValue(provinceList.get(x));
                    }
                    // 将具体的数据写入到每一行中，行开头为父级区域，后面是子区域。
                    Map<String, List<String>> areaMap = CrmExcelUtil.getAreaMap();
                    for (String key : areaMap.keySet()) {
                        List<String> son = areaMap.get(key);
                        Row subRow = hideSheet.createRow(rowId++);
                        subRow.createCell(0).setCellValue(key);
                        for (int x = 0; x < son.size(); x++) {
                            Cell cell = subRow.createCell(x + 1);
                            cell.setCellValue(son.get(x));
                        }
                        // 添加名称管理器
                        String range = CrmExcelUtil.getRange(1, rowId, son.size());
                        Name name = wb.createName();
                        // key不可重复
                        name.setNameName(key);
                        String formula = "address!" + range;
                        name.setRefersToFormula(formula);
                    }
                    // 省级下拉框
                    CellRangeAddressList provRangeAddressList = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    String[] arr = provinceList.toArray(new String[]{});
                    DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(arr);
                    HSSFDataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint);
                    provinceDataValidation.createErrorBox("error", "请选择正确的省份");
                    sheet.addValidationData(provinceDataValidation);
                    //市 区下拉框
                    for (int x = 2; x < 10000; x++) {
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 1), sheet, x, i + 1);
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 2), sheet, x, i + 2);
                    }
                } else {
                    HSSFCell cell = row.createCell(i);
                    if (record.getInt("is_null") == 1) {
                        cell.setCellValue(record.getStr("name") + "(*)");
                    } else {
                        cell.setCellValue(record.getStr("name"));
                    }
                    String[] setting = record.get("setting");
                    if (setting != null && setting.length != 0) {
                        CellRangeAddressList regions = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                        DVConstraint constraint = DVConstraint.createExplicitListConstraint(setting);
                        HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
                        sheet.addValidationData(dataValidation);
                    }
                }
            }
            HttpServletResponse response = getResponse();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=supplier_import.xls");
            wb.write(response.getOutputStream());

        } catch (Exception e) {
            Log.getLog(getClass()).error("error", e);
        } finally {
            try {
                wb.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }
        renderNull();
    }

    /**
     * @author jiang.xue
     * 导入供应商
     */
    @Permissions("finance:supplier:excelimport")
    @ActionApi(summary = "导入供应商", remark="导入供应商")
    public void uploadExcel() {
        String prefix= BaseUtil.getDate();
        UploadFile file=getFile("file",prefix);
        Integer repeatHandling=getParaToInt("repeatHandling");
        Long ownerUserId=getParaToLong("ownerUserId");
        CrmExcelUtil excelUtil=new CrmExcelUtil();
        Long messageId = excelUtil.addWork(CrmEnum.FINANCE_SUPPLIER,file.getFile().getAbsolutePath(),ownerUserId,repeatHandling,2);
        renderJson(R.ok().put("data",messageId));
    }

    /**
     * @author jiang.xue
     * 供应商批量导出
     */
    @Permissions("finance:supplier:excelexport")
    @ActionApi(summary = "供应商批量导出", remark="供应商批量导出")
    public void batchExportExcel(BasePageRequest basePageRequest){
        JSONObject jsonObject=basePageRequest.getJsonObject();
        Integer type = Integer.parseInt(jsonObject.getString("type"));
        String ids=jsonObject.getString("ids");
        JSONObject data =new JSONObject();
        data.fluentPut("supplierExport",new JSONObject().fluentPut("name","supplier_id").fluentPut("condition","in").fluentPut("value", ids));
        jsonObject.fluentPut("data",data).fluentPut("search","").fluentPut("type",2);
        basePageRequest.setJsonObject(jsonObject);
        JSONObject resultData = (JSONObject)supplierService.getSupplierPageList(basePageRequest).get("data");
        List<Record> recordList = resultData.getJSONArray("list").toJavaList(Record.class);
        export(recordList,type);
        renderNull();
    }

    /**
     * @author jiang.xue
     * 供应商导出
     */
    @Permissions("finance:supplier:excelexport")
    @ActionApi(summary = "供应商全部导出", remark="供应商全部导出")
    public void allExportExcel(BasePageRequest basePageRequest){
        JSONObject jsonObject = basePageRequest.getJsonObject();
        Integer type = CrmEnum.FINANCE_SUPPLIER.getType();// Integer.parseInt(jsonObject.getString("type"));
        jsonObject.fluentPut("excel", "yes");
        jsonObject.fluentPut("type", type);
//        AdminSceneService adminSceneService = new AdminSceneService();
        JSONObject data = (JSONObject)supplierService.filterConditionAndGetPageList(basePageRequest).get("data");
        List<Record> recordList = data.getJSONArray("list").toJavaList(Record.class);
        export(recordList,type);
        renderNull();
    }

    private void export(List<Record> recordList,Integer type){

        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            AdminFieldSort adminFieldSort = new AdminFieldSort();
            adminFieldSort.setLabel(type);
            List<Record> headList = Aop.get(AdminFieldService.class).queryListHead(adminFieldSort);
            headList.forEach(head -> writer.addHeaderAlias(StrUtil.toUnderlineCase(head.getStr("fieldName")), head.getStr("name")));
            writer.merge(headList.size() - 1, "供应商信息");
            HttpServletResponse response = getResponse();
            List<Map<String, Object>> list = new ArrayList<>();
            if (recordList.size() == 0) {
                Record record = new Record();
                headList.forEach(head -> record.set(StrUtil.toUnderlineCase(head.getStr("fieldName")), ""));
                list.add(record.getColumns());
            }
            recordList.forEach(record -> list.add(record.getColumns()));
            writer.setOnlyAlias(true);
            writer.write(list, true);
            writer.setRowHeight(0, 20);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=supplier.xls");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);
        } catch (Exception e) {
            Log.getLog(getClass()).error("导出供应商错误：",e);
        }
    }
}
